<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html>
<head>
<link href="sound.css" rel="stylesheet" type="text/css" />
<title>Crunchy Sound Reference</title>
</head>
<body>
<h1>Sound API</h1>
<p>The sound API in Crunchy is contained in soundout.py.  It is provided
as a simple teaching tool.</p>
<p>soundout.py can produce sound using one of 3 methods:</p>
<ol>
	<li>Crunchy will first attempt to use the Open Sound System (OSS). In OSS 
mode, sound playing blocks execution.</li>
	<li>If OSS is not available, Crunchy will assume it is running on Windows 
and attempt to load	the 'winsound' module from the Python Standard Library. 
By default it will then synthesize a waveform 
	internally and pass that to the relevant sound function. Or...</li>
	<li>...if <code>approximate=True</code> is passed to the relevant function, Crunchy will use the Windows SystemBeep function to play the sound. Both Windows modes are non-blocking.</li>
</ol>
<p>Note that, in both OSS and Windows Wave modes there is an appreciable delay between calling play and the sound actually being played;
this is because Crunchy has to synthesise the waveform itself.
Also, at present Crunchy can only generate sine waves - this might change in the future.</p>

<p>Four functions are provided.</p>

<p><span class="def">play_tone(freq, duration [, approximate])</span> plays a single sine waves at a given frequency.</p>
<p><span class="def">play_tones((freq1, freq2, ...), duration)</span> shows the effect of adding two or more sinusoidal sine waves with different frequencies.  When both frequencies are close to each other (try a difference of 1 Hz), we can hear a beat frequency.</p>
<p><span class="def">play_harmonics(freq, time, (amp1, amp2, amp3, ...), duration)</span> 
shows the effect of different <em>harmonics</em> (integer multiple of 
fundamental frequency) with relative amplitudes.  This may be
used to explain the concept of <em>timbre</em> of a musical instrument.</p>
<p><span class="def">play_song(song_data [, approximate])</span> plays a song defined
as a list of notes.</p>
<p>Notes are represented in strings as colon separated pairs of tone:time, where time is a multiple of 1 crotchet.
Tones are represented by their musical names (as used in the UK, anyway). 
'a' is concert a (440Hz), 'A' (the lowest 
note available) is one octave below (220Hz) and a1 is an octave above (880Hz). The highest tone available is b1 (987.8Hz).
A '#' is appended to tones to indicate 'sharp', and a 'b' is appended to indicate 'flat'. A rest (pause) is indicated by an underscore '_'.
A sequence of notes is represented as a space separated string.</p>
<p>For example:</p>
<ul>
<li>A single quaver at concert a: <span class="notes">"a:0.5"</span></li>
<li>The C-Major scale in crotchets: <span class="notes">"c:1&nbsp;d:1&nbsp;e:1&nbsp;f:1&nbsp;g:1&nbsp;a:1&nbsp;b:1&nbsp;c1:1&nbsp;_:1&nbsp;c1:1&nbsp;b:1&nbsp;a:1&nbsp;g:1&nbsp;f:1&nbsp;e:1&nbsp;d:1&nbsp;c:1"</span></li>
<li>A whole-tone scale on g: <span class="notes">"g:1&nbsp;a:1&nbsp;b:1&nbsp;c1#:1&nbsp;e1b:1&nbsp;f1:1&nbsp;g1:1"</span></li>
</ul>
<p>For convenience, two songs are predefined (<span class="def">yesterday, ode_to_joy</span>) as a list of notes, as well as the chromatic scale, <span class="def">chromatic</span>.</p>
<p>There appears to be a bug in the Python Standard Library sound generation 
routines such that tones with frequencies multiple of 233.1 Hz are "noisy".  
When playing pure tones (play_song, play_tone, play_harmonics) at exact 
integer multiples of 233.1 Hz (rounded to 1 decimal place), the frequency 
produced by Crunchy is actually slightly shifted from that requested, thus 
hiding the "noisy bug".  To reproduce the bug, try <code>play_tones((233.1, 
233.1), 3)</code></p>
</body>
</html>
